package com.iflytek.aidemo.util;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.CompleteMultipartUploadResult;
import com.alibaba.sdk.android.oss.model.MultipartUploadRequest;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.iflytek.aidemo.util.OssAddBean;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

/**
 * oss
 */
public class OssUtil {

    private static final String TAG = "=====OssUtil===>>>";
    private Context context;
    private String uploadFilePath ;//上传文件目录名称
    private String filehttpUrl;//图片,视频 统一访问地址
    private String accessKeyId;
    private String bucketName;
    private String accessKeySecret;
    private String accessToken;
    private String endpoint;
    private int number;
    public OSSUploadHelperCallback callback;
    private OSS client;
    List<String> successPath = new ArrayList<>();
    Map<String, String> successPathMap = new IdentityHashMap<String, String>();

    public OssUtil(Context context, String filehttpUrl, String uploadFilePath, String accessToken, String accessKeyId, String accessKeySecret, String endpoint, String bucketName) {
        this.context = context;
        this.filehttpUrl = filehttpUrl;
        this.uploadFilePath = uploadFilePath;
        this.endpoint = endpoint;
        this.bucketName = bucketName;
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.accessToken = accessToken;
    }

    public void OSSStas() {
        getNetOssStsToken();
    }

    //OSS的配置,建议只实例化一次，即不要放在循环体中。
    public OSS getOSSClient() {
        if (false) {
            OSSLog.enableLog();
        }
        if (context == null) {
            Log.e(TAG, "OSS客户端创建失败 - Context为null");
            return null;
        }

        if (TextUtils.isEmpty(endpoint) || TextUtils.isEmpty(bucketName) ||
                TextUtils.isEmpty(accessKeyId) || TextUtils.isEmpty(accessToken)) {
            Log.e(TAG, "OSS客户端创建失败 - 关键参数缺失");
            Log.e(TAG, "endpoint: " + endpoint);
            Log.e(TAG, "bucketName: " + bucketName);
            Log.e(TAG, "accessKeyId: " + accessKeyId);
            Log.e(TAG, "accessToken: " + (accessToken != null ? "***" : "null"));
            return null;
        }
        //这个初始化安全性没有Sts安全
//        OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);

        // 推荐使用
        OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(accessKeyId, accessKeySecret, accessToken);

        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // 连接超时，默认15秒
        conf.setSocketTimeout(15 * 1000); // socket超时，默认15秒
        conf.setMaxConcurrentRequest(5); // 最大并发请求数，默认5个
        conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次

        client = new OSSClient(context, endpoint, credentialProvider, conf);
        Log.d(TAG, "OSS客户端创建成功，endpoint: " + endpoint);
        return client;

    }

    /**
     * 多图片上传方法
     *
     * @param paths 需上传文件的路径
     */
    private void uploads(final List<String> paths) {
        Log.d(TAG,"上传开始");
        if (client == null) {
            getNetOssStsToken();
            Log.d(TAG,"上传开始2");
//            return;
        }
        successPath.clear();
        successPathMap.clear();
        Log.d(TAG,"上传开始1");
        number = 1;
        for (String path : paths) {
            // 构造上传请求
            PutObjectRequest request = new PutObjectRequest(bucketName, getObjectKey(path), path);
            // 异步上传可回调上传进度。
            request.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
                @Override
                public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                    Log.d(TAG, "PutObject"+"currentSize: " + currentSize + " totalSize: " + totalSize);
                    int progress = (int) (100 * currentSize / totalSize);
                    Log.d(TAG,"上传进度="+progress);
//                    上传成功
//                    successPath.add(getAllPath(request.getObjectKey()));
//                    successPathMap.put(request.getUploadFilePath(),getAllPath(request.getObjectKey()));
//                    if (number == paths.size() && callback != null) {
//                        callback.onSuccess(successPath);
//                    }
//                    if (number == paths.size() && callbackmap != null) {
//                        callbackmap.onSuccess(successPathMap);
//                    }
//                    number++;
                }
            });

            //同步上传回调
            OSSAsyncTask ptask = client.asyncPutObject(request, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                @Override
                public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                    Log.e(TAG, request.getUploadFilePath() + "===上传成功11== ：" + getAllPath(request.getObjectKey()));
                    //上传成功
                    successPath.add(getAllPath(request.getObjectKey()));
                    successPathMap.put(new String(request.getUploadFilePath()), getAllPath(request.getObjectKey()));
                    if (number == paths.size() && callback != null) {
                        callback.onSuccess(successPath);
                        callback.onSuccess(successPathMap);
                    }
                    number++;
                }

                @Override
                public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                    //上传失败
                    if (callback != null) {
                        callback.onFailure(clientException, serviceException);
                    }

                    if (clientException != null) {
                        // 本地异常如网络异常等
                        Log.e(TAG, "UploadFailure：表示向OSS发送请求或解析来自OSS的响应时发生错误。\n" +
                                "  *例如，当网络不可用时，这个异常将被抛出");
                        Log.e(TAG, "ErrorCode ：" + clientException.getMessage());
                        Log.e(TAG, "==========================================");
                        clientException.printStackTrace();
                    }

                    if (serviceException != null) {
                        // 服务异常
                        Log.e(TAG, "===UploadFailure：表示在OSS服务端发生错误====");
                        Log.e(TAG, "ErrorCode ：" + serviceException.getErrorCode());
                        Log.e(TAG, "RequestId ：" + serviceException.getRequestId());
                        Log.e(TAG, "HostId ：" + serviceException.getHostId());
                        Log.e(TAG, "RawMessage ：" + serviceException.getRawMessage());
                        Log.e(TAG, "==========================================");
//                        if(serviceException.getErrorCode().equals("InvalidAccessKeyId")){
//                            //token过期
//                            getNetOssStsToken();
//                        }
                    }

                }

            });
            //ptask.cancel(); // 可以取消任务
            //ptask.waitUntilFinished(); // 可以等待直到任务完成

        }
    }

    /**
     * 分片上传
     */
    private long ztotalSize;//多个文件总size
    private long scZtotalSize;//多个文件上传的总size

    public void uploadMultipart(final List<String> paths, final OSSUploadHelperCallback callback) {
        this.callback = callback;
        if (client == null) {
            return;
        }
        ztotalSize = 0;
        scZtotalSize = 0;
        successPath.clear();
        successPathMap.clear();
        number = 1;
        for (String path : paths) {
            MultipartUploadRequest request = new MultipartUploadRequest(bucketName, getObjectKey(path), path);
            // 回调上传进度。
            File file = new File(path);
            ztotalSize += file.length();
            request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() {
                @Override
                public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) {
                    Log.e(TAG, request.getUploadFilePath() + "===上传成功== ：" + request.getObjectKey());
//                    Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
                    if (currentSize == totalSize) {//表示第N个文件传完
                        if (!paths.get(paths.size() - 1).equals(request.getUploadFilePath())) {//还要判断是否是最后一个文件
                            scZtotalSize += totalSize;
                            currentSize = 0;
                        }
                    }
                    int progress = (int) (100 * (currentSize + scZtotalSize) / ztotalSize);
                    Log.d(TAG, "上传进度=" + progress);
                    callback.onProgres(progress);
                }
            });

            //同步上传回调
            OSSAsyncTask task = client.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() {
                @Override
                public void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result) {
//                    Log.e(TAG, request.getUploadFilePath()+"===上传成功== ：" + request.getObjectKey());
                    //上传成功
                    successPath.add(getAllPath(request.getObjectKey()));
                    successPathMap.put(new String(request.getUploadFilePath()), getAllPath(request.getObjectKey()));
                    if (number == paths.size() && callback != null) {
                        callback.onSuccess(successPath);
                        callback.onSuccess(successPathMap);
                    }
                    number++;
                }

                @Override
                public void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException) {
                    OSSLog.logError(serviceException.getRawMessage());
                    //上传失败
                    if (callback != null) {
                        callback.onFailure(clientException, serviceException);
                    }


                    if (clientException != null) {
                        // 本地异常如网络异常等
                        Log.e(TAG, "UploadFailure：表示向OSS发送请求或解析来自OSS的响应时发生错误。\n" +
                                "  *例如，当网络不可用时，这个异常将被抛出");
                        Log.e(TAG, "ErrorCode ：" + clientException.getMessage());
                        Log.e(TAG, "==========================================");
                        clientException.printStackTrace();
                    }

                    if (serviceException != null) {
                        // 服务异常
                        Log.e(TAG, "===UploadFailure：表示在OSS服务端发生错误====");
                        Log.e(TAG, "ErrorCode ：" + serviceException.getErrorCode());
                        Log.e(TAG, "RequestId ：" + serviceException.getRequestId());
                        Log.e(TAG, "HostId ：" + serviceException.getHostId());
                        Log.e(TAG, "RawMessage ：" + serviceException.getRawMessage());
                        Log.e(TAG, "==========================================");
//                        if(serviceException.getErrorCode().equals("InvalidAccessKeyId")){
//                            //token过期
//                            getNetOssStsToken();
//                        }
                    }
                }
            });
            //task.cancel();//取消分片上传。
            //task.waitUntilFinished();// 可以等待直到任务完成


        }
    }


    /**
     * 分片上传
     */
    public List<OssAddBean> successBean = new ArrayList<>();

    public void uploadMultipartBean(final List<OssAddBean> ossAddBeans, final OSSUploadHelperCallback callback) {
        this.callback = callback;
        if (client == null) {
            return;
        }
        ztotalSize = 0;
        scZtotalSize = 0;
        successPath.clear();
        successPathMap.clear();
        number = 1;
        for (final OssAddBean ossbean : ossAddBeans) {
            MultipartUploadRequest request = new MultipartUploadRequest(bucketName, getObjectKey(ossbean.getPaths()), ossbean.getPaths());
            // 回调上传进度。
            File file = new File(ossbean.getPaths());
            ztotalSize += file.length();
            request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() {
                @Override
                public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) {
//                    Log.e(TAG, request.getUploadFilePath()+"===上传成功== ：" + request.getObjectKey());
//                    Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
                    if (currentSize == totalSize) {//表示第N个文件传完
                        if (!ossAddBeans.get(ossAddBeans.size() - 1).equals(request.getUploadFilePath())) {//还要判断是否是最后一个文件
                            scZtotalSize += totalSize;
                            currentSize = 0;
                        }
                    }
                    int progress = (int) (100 * (currentSize + scZtotalSize) / ztotalSize);
                    Log.d(TAG, "上传进度=" + progress);
                    callback.onProgres(progress);
                }
            });

            //同步上传回调
            OSSAsyncTask task = client.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() {
                @Override
                public void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result) {
//                    Log.e(TAG, ossbean.getType()+"===上传成功== ：" + request.getObjectKey());
                    //上传成功
                    successBean.add(new OssAddBean(ossbean.getIndex(), getAllPath(request.getObjectKey()), ossbean.getIde(), ossbean.getType()));
                    if (number == ossAddBeans.size() && successBean != null) {
                        callback.onSuccessben(successBean);
                    }
                    number++;
                }

                @Override
                public void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException) {
                    OSSLog.logError(serviceException.getRawMessage());
                    //上传失败
                    if (callback != null) {
                        callback.onFailure(clientException, serviceException);
                    }


                    if (clientException != null) {
                        // 本地异常如网络异常等
                        Log.e(TAG, "UploadFailure：表示向OSS发送请求或解析来自OSS的响应时发生错误。\n" +
                                "  *例如，当网络不可用时，这个异常将被抛出");
                        Log.e(TAG, "ErrorCode ：" + clientException.getMessage());
                        Log.e(TAG, "==========================================");
                        clientException.printStackTrace();
                    }

                    if (serviceException != null) {
                        // 服务异常
                        Log.e(TAG, "===UploadFailure：表示在OSS服务端发生错误====");
                        Log.e(TAG, "ErrorCode ：" + serviceException.getErrorCode());
                        Log.e(TAG, "RequestId ：" + serviceException.getRequestId());
                        Log.e(TAG, "HostId ：" + serviceException.getHostId());
                        Log.e(TAG, "RawMessage ：" + serviceException.getRawMessage());
                        Log.e(TAG, "==========================================");
//                        if(serviceException.getErrorCode().equals("InvalidAccessKeyId")){
//                            //token过期
//                            getNetOssStsToken();
//                        }
                    }
                }
            });
            //task.cancel();//取消分片上传。
            //task.waitUntilFinished();// 可以等待直到任务完成


        }
    }


    // 拼接自己服务器的URL
    private String getAllPath(String objectKey) {
        String imageUrl = "";
        if (!TextUtils.isEmpty(objectKey)) {
//            int i = objectKey.lastIndexOf("/");
//            String substring = objectKey.substring(i + 1, objectKey.length());
//            imageUrl = imghttpUrl + uploadFilePath + substring;
//            Log.e("Oss==>>", substring);
//            Log.e("Oss==>>", imageUrl);

            imageUrl = filehttpUrl + objectKey;

        }
        return imageUrl;
    }


    /**
     * 上传单个文件   (图片,视频,gif,.....)
     *
     * @param path     本地地址
     * @param callback 成功回调
     */
    public void uploadImage(String path, OSSUploadHelperCallback callback) {
        Log.d(TAG,"上传开始");
        this.callback = callback;
        List<String> strings = new ArrayList<>();
        strings.add(path);
        uploads(strings);
    }


    /**
     * 上传多文件   (图片,视频,gif,.....)
     *
     * @param paths    本地地址
     * @param callback 成功回调
     */
    public void uploadImages(List<String> paths, OSSUploadHelperCallback callback) {
        this.callback = callback;
        uploads(paths);
    }


    /**
     * 获取OssToken    并上传文件
     *
     * @param path     本地地址
     * @param callback 成功回调
     */
//    public void uploadImageT(Context context, String path, OSSUploadHelperCallback callback) {
//        this.callback = callback;
//        OkGo.<BaseRespose<OSSTokenBean>>post(Api.formatUrl("/XinBu/OssValues?user=lianyou-oss&token=5c413c4158db33132824a16e"))
//                .tag(context)
//                .execute(new DialogCallback<BaseRespose<OSSTokenBean>>(context, false) {
//                    @Override
//                    public void onSuccess(Response<BaseRespose<OSSTokenBean>> response) {
//                        OSSTokenBean ossTokenBean = response.body().data;
//                        ENDPOINT = ossTokenBean.getPoint();
//                        BUCKET_NAME = ossTokenBean.getDucketName();
//                        OSS_ACCESS_KEY_ID = ossTokenBean.getAccessKeyId();
//                        OSS_ACCESS_KEY_SECRET = ossTokenBean.getAccessKeySecret();
//                        uploadFilePath = ossTokenBean.getUploadFilePath();
//                        //得到client
//                        client = getOSSClient();
//                        List<String> strings = new ArrayList<>();
//                        strings.add(path);
//                        uploads(strings);
//                    }
//                });
//    }


    /**
     * 取得系统时间
     *
     * @return 时间戳
     */
    private String getDateString() {
        return System.currentTimeMillis() + "";
    }

    /**
     * 返回key
     *
     * @param path 本地路径
     * @return key
     */
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");// 格式化时间
    private Date date = new Date();// 获取当前时间

    //格式: app/uploadFilePath/2021/04/21/sfdsgfsdvsdfdsfs.jpg
    private String getObjectKey(String path) {
        Log.e("Oss==>>", path);

        // 1. 修改日期格式为 yyyy-MM-dd
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = sdf.format(date);

        // 2. 获取时间戳
        String timestamp = getDateString();

        // 3. 拼接路径：uploadFilePath/yyyy-MM-dd-时间戳.后缀
        String objectKey = String.format(
                uploadFilePath + "%s-%s.%s",
                formattedDate,
                timestamp,
                getFormatName(path)
        );

        Log.e("Oss==>>", objectKey);
        return objectKey;
    }
    /**
     * 获取文件格式名
     */
    private String getFormatName(String fileName) {
        //去掉首尾的空格
        fileName = fileName.trim();
        String s[] = fileName.split("\\.");
        if (s.length >= 2) {
            return s[s.length - 1];
        }
        return "";
    }

    public interface OSSUploadHelperCallback {
        //list上传成功
        void onSuccess(List<String> allPath);

        //map上传成功
        void onSuccess(Map<String, String> allPathMap);

        //bean上传成功
        void onSuccessben(List<OssAddBean> allossbean);

        //上传失败
        void onFailure(ClientException clientException, ServiceException serviceException);

        //上传进度
        void onProgres(int progress);
    }

    /**
     * 获取Oss 的ststoken
     */
    public void getNetOssStsToken() {
        bucketName = KeyConfig.bucketName;
        // SpUtil.get(KeyConfig.bucketName, "");
        accessKeyId = KeyConfig.accessKeyId;
        // SpUtil.get(KeyConfig.accessKeyId, "");
        accessKeySecret = KeyConfig.accessKeySecret;
        // SpUtil.get(KeyConfig.accessKeySecret, "");
        accessToken = KeyConfig.accessStsToken;
        // SpUtil.get(KeyConfig.accessStsToken, "");
        endpoint = KeyConfig.endpoint;
        // SpUtil.get(KeyConfig.endpoint, "");
        filehttpUrl = KeyConfig.osstpdz;
        // SpUtil.get(KeyConfig.osstpdz, "");
        //得到client
        client = getOSSClient();

    }

}